package com.ruoyi.business.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.bizsys.domain.ExtMonnifyOrder;
import com.ruoyi.bizsys.domain.LoanIou;
import com.ruoyi.bizsys.domain.RepaymentOrder;
import com.ruoyi.bizsys.mapper.ExtMonnifyReservedAccountsMapper;
import com.ruoyi.bizsys.service.*;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.business.domain.TransferVo;
import com.ruoyi.business.service.*;
import com.ruoyi.business.util.MonnifyUtils;
import com.ruoyi.business.util.RepaymentUtils;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.RspEnmu;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.extdata.common.config.MonnifyConfig;
import com.ruoyi.system.service.ISysDictDataService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class MonnifyRepaymentServiceImpl implements IMonnifyRepaymentService {

    @Autowired
    private IExtMonnifyOrderService iExtMonnifyOrderService;

    @Autowired
    IBLoanInfoService loanInfoService;

    @Autowired
    RedisCache redisCache;

    @Autowired
    IRepaymentSmsService iRepaymentSmsService;

    @Autowired
    IRepaymentOrderService repaymentOrderService;

    @Autowired
    IDoRepaymentLastService doRepaymentLastService;

    @Autowired
    ILoanOverflowService iLoanOverflowService;

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    ICreditAccountService creditAccountService;

    @Autowired
    ILoanIouService iLoanIouService;

    @Autowired
    IRepaymentService repaymentService;

    @Autowired
    IBRepaymentService iBRepaymentService;

    @Autowired
    MonnifyConfig monnifyConfig;

    @Autowired
    IMonnifyService monnifyService;

    @Autowired
    ExtMonnifyReservedAccountsMapper extMonnifyReservedAccountsMapper;

    @Autowired
    IBLoanInfoService bLoanInfoService;

    @Autowired
    IRepayToWalletService repayToWalletService;

    @Autowired
    ISysDictDataService sysDictDataService;

    public static void main(String[] args) {
        String secretKey = "BXG3L6GZGAJ7D4A67FMJHR4Z92DL668Q";
        String paymentReference = "MNFY|99|20220114044219|020902";
        String amountPaid = "2000.00";
        String paidOn = "14/01/2022 04:42:19 AM";
        String transactionReference = "MNFY|99|20220114044219|020902";
        String sha = MonnifyUtils.SHA(secretKey + "|" + paymentReference + "|" + amountPaid + "|" + paidOn + "|" + transactionReference);
        System.out.println(sha);
    }

    @Override
    public ExtMonnifyOrder checkWebHookStatus(JSONObject jsonObject, String custNo) {

        try {
            //1.对比hash值
            //{clientSecret} | {paymentReference} | {amountPaid} | {paidOn} | {transactionReference}
//            String sha = MonnifyUtils.SHA(monnifyConfig.getSecretKey() + "|" + jsonObject.getString("paymentReference") + "|" + jsonObject.getString("amountPaid") + "|" + jsonObject.getString("paidOn") + "|" + jsonObject.getString("transactionReference"));
//            if (!sha.equals(jsonObject.getString("transactionHash"))) {
//                throw new BusinessException("transactionHash error", RspEnmu.MONNIFY_TRANSACTION_WEBHOOK_ILLEGAL_REQUEST);
//            }

            //2.主动请求第三方查询该订单状态
//        String token = IExternalApiService.monnifyAuthLogin();
//        JSONObject transactionReference = IExternalApiService.monnifyGetTransactionStatus(parseObject.getString("transactionReference"), token);
//        if(!transactionReference.getString("paymentStatus").equals("PAID")){
//            throw new BusinessException(transactionReference.getString("paymentStatus"), RspEnmu.MONNIFY_TRANSACTION_WEBHOOK_STATUS_ERROR);
//        }

            JSONObject product = jsonObject.getJSONObject("product");
            if (product == null) {
                throw new BusinessException("", RspEnmu.SYSTEM_ERR);
            }

            if (!"PAID".equals(jsonObject.get("paymentStatus"))) {
                throw new BusinessException(jsonObject.getString("paymentStatus"), RspEnmu.MONNIFY_TRANSACTION_WEBHOOK_STATUS_ERROR);
            }
            ExtMonnifyOrder extMonnifyOrder = MonnifyUtils.setExtMonnifyOrderWebHook(jsonObject, custNo);
            extMonnifyOrder.setSourceData(jsonObject.toString());
            iExtMonnifyOrderService.insertExtMonnifyOrder(extMonnifyOrder);
            return extMonnifyOrder;
        } catch (Exception e) {
            log.error("保存 MonnifyOrder 异常", e);
            return null;
        }
    }

    @Override
    public ExtMonnifyOrder checkInterfaceStatus(JSONObject jsonObject, String accountReference, String custNo) {
        try {
            String paymentStatus = jsonObject.getString("paymentStatus");
            if ("PAID".equals(paymentStatus)) {
                // ExtMonnifyReservedAccounts extMonnifyReservedAccounts = extMonnifyReservedAccountsMapper.selectByAccountReference(accountReference);
                ExtMonnifyOrder extMonnifyOrder = MonnifyUtils.setExtMonnifyOrderInterface(jsonObject, accountReference, custNo);
                iExtMonnifyOrderService.insertExtMonnifyOrder(extMonnifyOrder);
                return extMonnifyOrder;
            } else {
                return null;
            }
        } catch (DuplicateKeyException e) {
            log.error("交易订单已经存在，跳过");
            return null;
        } catch (Exception e) {
            log.error("保存ExtMonnifyOrder异常：", e);
            return null;
        }
    }


    @Transactional
    @Override
    public void repaymentLock(ExtMonnifyOrder extMonnifyOrder) {
        //锁住客户账户再操作
        String lockKey = RedisCache.CUST_ACCOUNT_LOCK_KEY_PREFIX + extMonnifyOrder.getCustNo();
        RLock lock = redisCache.lock(lockKey);
        long start = System.currentTimeMillis();
        try {
            Date paidOn = DateUtils.parseDate(extMonnifyOrder.getPaidOn());
            extMonnifyOrder.setStatus(1);
            iExtMonnifyOrderService.updateExtMonnifyOrder(extMonnifyOrder);

            String repayToWalletSwitch = sysDictDataService.selectDictLabel("biz_switch", "repay_to_wallet_switch");
            if (StringUtils.equals(BizConstants.BIZ_SWITCH_OPEN, repayToWalletSwitch)) {
                log.info("Monnify VA 还款金额直接充值钱包开关开启，不进入还款");

                TransferVo transferVo = TransferVo.builder().custNo(extMonnifyOrder.getCustNo()).transferAmt(extMonnifyOrder.getAmountPaid()).payTime(paidOn).actionType(BizConstants.OVERFLOW_TYPE_MONNIFY_CHARGE).reference(extMonnifyOrder.getTransactionReference()).build();
                repayToWalletService.addOverflowAndPushWallet(transferVo);
                return;
            }

            log.info("还款金额直接充值钱包开关关闭，进入正常还款");

            boolean repaymentData = getRepaymentData(extMonnifyOrder.getAmountPaid(), paidOn, extMonnifyOrder.getCustNo(), extMonnifyOrder.getTransactionReference());
            if (!repaymentData) {
                log.info("无在贷借据，Monnfiy 交易款进入溢缴款");
                TransferVo transferVo = TransferVo.builder().custNo(extMonnifyOrder.getCustNo()).transferAmt(extMonnifyOrder.getAmountPaid()).payTime(paidOn).actionType(BizConstants.OVERFLOW_TYPE_REPEAT_TRANSFERTOUS).reference(extMonnifyOrder.getTransactionReference()).build();
                repayToWalletService.addOverflowAndPushWallet(transferVo);
            }
        } catch (Exception e) {
            log.error("Repayment 线程 sleep 异常", e);
            iBRepaymentService.saveRepaymentException(extMonnifyOrder.getTransactionReference(), BizConstants.REPAYMENT_EXCEPTION_TYPE_MONNIFY, extMonnifyOrder.getAmountPaid(), extMonnifyOrder.getCustNo());
            throw new RuntimeException(e);
        } finally {
            long end = System.currentTimeMillis();
            log.info("锁占用时间，耗时：" + (end - start) + " ms");
            lock.unlock();
        }
    }

    @Override
    public void initRepaymentOrder(LoanIou loanIou) {

        List<RepaymentOrder> toActionTypeAndLoanSerialNo = repaymentService.getToActionTypeAndLoanSerialNo(BizConstants.LOAN_REPAYMENT_ORDER_TYPE_TTS, loanIou.getLoanSerialNo());
        if (!CollectionUtils.isEmpty(toActionTypeAndLoanSerialNo)) {
            return;
        }

        //添加数据
        RepaymentOrder repaymentOrder = repaymentService.initRepaymentOrderFromLoanIou(loanIou,
                BizConstants.LOAN_REPAYMENT_ORDER_TYPE_TTS, BigDecimal.ZERO);
        repaymentOrderService.insertRepaymentOrder(repaymentOrder);
    }

    /**
     * 获取下一笔冲账的数据
     *
     * @param amountPaid
     * @param payTime
     * @param custNo
     * @param transactionReference
     * @return
     */
    private boolean getRepaymentData(BigDecimal amountPaid, Date payTime, String custNo, String transactionReference) {
        List<LoanIou> loanIouList = loanInfoService.getFirstByCustNo(custNo);
        if (loanIouList != null && loanIouList.size() > 0) {
            LoanIou loanIou = loanIouList.get(0);
            //3.查询该loanIou有无repaymentOrder记录，且支付方式是ttu，且是未完成的，无则新增，有则冲账
            List<RepaymentOrder> repaymentOrders = repaymentService.getToActionTypeAndLoanSerialNo(BizConstants.LOAN_REPAYMENT_ORDER_TYPE_TTS, loanIou.getLoanSerialNo());

            RepaymentOrder repaymentOrder;

            if (repaymentOrders == null || repaymentOrders.size() == 0) {
                //新增repaymentOrder
                repaymentOrder = RepaymentUtils.createRepaymentOrder(loanIou, BizConstants.LOAN_REPAYMENT_ORDER_TYPE_TTS);
                repaymentOrder.setPayTransSerialNo(transactionReference);
                repaymentOrder.setPayTime(payTime);
                repaymentOrder.setRepayStatus(BizConstants.REPAYMENT_ORDER_STATUS_SUCCESS);
                repaymentOrderService.insertRepaymentOrder(repaymentOrder);

            } else {
                repaymentOrder = repaymentOrders.get(0);
                repaymentOrder.setPayTransSerialNo(transactionReference);
                repaymentOrder.setPayTime(payTime);
                repaymentOrder.setRepayStatus(BizConstants.REPAYMENT_ORDER_STATUS_SUCCESS);
                repaymentOrderService.updateRepaymentOrder(repaymentOrder);
            }

            repaymentOrder.setRepaymentAmt(amountPaid);
            repaymentOrder.setRepayStatus(BizConstants.REPAYMENT_ORDER_STATUS_SUCCESS);
            repaymentOrderService.updateRepaymentOrder(repaymentOrder);

            monnifyRepayment(repaymentOrder, amountPaid, "TTS-GetStatus");

            doRepaymentLastService.lastInitRuleInAndAutoMat(repaymentOrder);
            return true;
        } else {
            return false;
        }
    }

    /**
     * monnify冲账
     *
     * @param repaymentOrder
     * @param amountPaid
     * @param reduceSource
     */
    private void monnifyRepayment(RepaymentOrder repaymentOrder, BigDecimal amountPaid, String reduceSource) {
        //如果成功，更新repaymentOrder表并执行冲账

        //更新repaymentOrder表
        BigDecimal oldAmountPaid = amountPaid;
        amountPaid = RepaymentUtils.setRepaymentAmount(amountPaid, repaymentOrder);

        //冲账
        repaymentService.repaymentNoLock(repaymentOrder);

        LoanIou loanIou = iLoanIouService.getLoanIouByLoanSerialNo(repaymentOrder.getLoanSerialNo());

        //全部充完  检查这一笔loan_iou金额
        iBRepaymentService.checkAmount(loanIou, reduceSource);
        //发送短信
        iRepaymentSmsService.monnify(loanIou, oldAmountPaid.subtract(amountPaid).setScale(2, BigDecimal.ROUND_UP));

        // 下面的代码不在处理多笔iou 2022/0704
//        if (amountPaid.doubleValue() > 0) {
//            boolean repaymentData = getRepaymentData(amountPaid, repaymentOrder.getPayTime(), repaymentOrder.getCustNo(), repaymentOrder.getPayTransSerialNo());
//            if (!repaymentData) {
//                LoanOverflow loanOverflow = new LoanOverflow();
//                loanOverflow.setChangeAmount(amountPaid);
//                loanOverflow.setCustNo(repaymentOrder.getCustNo());
//                loanOverflow.setOverflowTime(repaymentOrder.getPayTime());
//                loanOverflow.setType(BizConstants.OVERFLOW_TYPE_OVERFLOW_TRANSFERTOUS);
//                loanOverflow.setRepaymentOrderNo(repaymentOrder.getRepaymentNo());
//                loanOverflow.setLoanIouNo(repaymentOrder.getLoanSerialNo());
//                iLoanOverflowService.insertLoanOverflow(loanOverflow);
//
//                //修改用户溢缴金额
//                creditAccountService.updateOverflowAmount(repaymentOrder.getCustNo(), amountPaid);
////            }
//            //发送短信
//            iRepaymentSmsService.monnify(loanIou, oldAmountPaid.subtract(amountPaid).setScale(2, BigDecimal.ROUND_UP));
//        } else {
//            //全部充完  检查这一笔loan_iou金额
//            iBRepaymentService.checkAmount(loanIou, reduceSource);
//            //发送短信
//            iRepaymentSmsService.monnify(loanIou, oldAmountPaid.subtract(amountPaid).setScale(2, BigDecimal.ROUND_UP));
//        }
    }

}
